#pragma once

#include <linux/types.h>

#define cmpxchg_relaxed(ptr, ...)                   \
	({                                              \
		typeof(ptr) __ai_ptr = (ptr);               \
		raw_cmpxchg_relaxed(__ai_ptr, __VA_ARGS__); \
	})

#define try_cmpxchg_relaxed(ptr, oldp, ...)                        \
	({                                                             \
		typeof(ptr) __ai_ptr = (ptr);                              \
		typeof(oldp) __ai_oldp = (oldp);                           \
		raw_try_cmpxchg_relaxed(__ai_ptr, __ai_oldp, __VA_ARGS__); \
	})

#define try_cmpxchg_release(ptr, oldp, ...)                        \
	({                                                             \
		typeof(ptr) __ai_ptr = (ptr);                              \
		typeof(oldp) __ai_oldp = (oldp);                           \
		raw_try_cmpxchg_release(__ai_ptr, __ai_oldp, __VA_ARGS__); \
	})

#define try_cmpxchg_acquire(ptr, oldp, ...)                        \
	({                                                             \
		typeof(ptr) __ai_ptr = (ptr);                              \
		typeof(oldp) __ai_oldp = (oldp);                           \
		raw_try_cmpxchg_acquire(__ai_ptr, __ai_oldp, __VA_ARGS__); \
	})

#define xchg_acquire(ptr, ...)                   \
	({                                           \
		typeof(ptr) __ai_ptr = (ptr);            \
		raw_xchg_acquire(__ai_ptr, __VA_ARGS__); \
	})

static inline int atomic_read(const atomic_t *v)
{
	return raw_atomic_read(v);
}

static inline void atomic_set(atomic_t *v, int i)
{
    raw_atomic_set(v, i);
}

static inline void atomic_inc(atomic_t *v)
{
	raw_atomic_inc(v);
}

/**
 * atomic_add_return_release() - atomic add with release ordering
 * @i: int value to add
 * @v: pointer to atomic_t
 *
 * Atomically updates @v to (@v + @i) with release ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_add_return_release() there.
 *
 * Return: The updated value of @v.
 */
static inline int atomic_add_return_release(int i, atomic_t *v)
{
	return raw_atomic_add_return_release(i, v);
}

/**
 * atomic_inc_return() - atomic increment with full ordering
 * @v: pointer to atomic_t
 *
 * Atomically updates @v to (@v + 1) with full ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_inc_return() there.
 *
 * Return: The updated value of @v.
 */
static inline int atomic_inc_return(atomic_t *v)
{
    return raw_atomic_inc_return(v);
}

/**
 * atomic_fetch_add() - atomic add with full ordering
 * @i: int value to add
 * @v: pointer to atomic_t
 *
 * Atomically updates @v to (@v + @i) with full ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_fetch_add() there.
 *
 * Return: The original value of @v.
 */
static inline int atomic_fetch_add(int i, atomic_t *v)
{
    return raw_atomic_fetch_add(i, v);
}

/**
 * atomic_try_cmpxchg() - atomic compare and exchange with full ordering
 * @v: pointer to atomic_t
 * @old: pointer to int value to compare with
 * @new: int value to assign
 *
 * If (@v == @old), atomically updates @v to @new with full ordering.
 * Otherwise, @v is not modified, @old is updated to the current value of @v,
 * and relaxed ordering is provided.
 *
 * Unsafe to use in noinstr code; use raw_atomic_try_cmpxchg() there.
 *
 * Return: @true if the exchange occured, @false otherwise.
 */
static inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
{
	return raw_atomic_try_cmpxchg(v, old, new);
}

/**
 * atomic_sub() - atomic subtract with relaxed ordering
 * @i: int value to subtract
 * @v: pointer to atomic_t
 *
 * Atomically updates @v to (@v - @i) with relaxed ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_sub() there.
 *
 * Return: Nothing.
 */
static inline void atomic_sub(int i, atomic_t *v)
{
    raw_atomic_sub(i, v);
}

/**
 * atomic_read_acquire() - atomic load with acquire ordering
 * @v: pointer to atomic_t
 *
 * Atomically loads the value of @v with acquire ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_read_acquire() there.
 *
 * Return: The value loaded from @v.
 */
static inline int atomic_read_acquire(const atomic_t *v)
{
    return raw_atomic_read_acquire(v);
}

/**
 * atomic_dec_and_test() - atomic decrement and test if zero with full ordering
 * @v: pointer to atomic_t
 *
 * Atomically updates @v to (@v - 1) with full ordering.
 *
 * Unsafe to use in noinstr code; use raw_atomic_dec_and_test() there.
 *
 * Return: @true if the resulting value of @v is zero, @false otherwise.
 */
static inline bool atomic_dec_and_test(atomic_t *v)
{
	//TODO
	return 0;//raw_atomic_dec_and_test(v);
}

/**
 * atomic_try_cmpxchg_acquire() - atomic compare and exchange with acquire ordering
 * @v: pointer to atomic_t
 * @old: pointer to int value to compare with
 * @new: int value to assign
 *
 * If (@v == @old), atomically updates @v to @new with acquire ordering.
 * Otherwise, @v is not modified, @old is updated to the current value of @v,
 * and relaxed ordering is provided.
 *
 * Unsafe to use in noinstr code; use raw_atomic_try_cmpxchg_acquire() there.
 *
 * Return: @true if the exchange occured, @false otherwise.
 */
static inline bool atomic_try_cmpxchg_acquire(atomic_t *v, int *old, int new)
{
    //TODO
	return 0;//raw_atomic_try_cmpxchg_acquire(v, old, new);
}
